#include "precompile.h"

#include "Main.h"
#include "MainDoc.h"
#include "MainView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

IMPLEMENT_DYNCREATE(CMainView, CScrollView)

BEGIN_MESSAGE_MAP(CMainView, CScrollView)
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_CREATE()
	ON_COMMAND(ID_FILE_PRINT, &CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMainView::OnFilePrintPreview)
END_MESSAGE_MAP()

BOOL CMainView::PreCreateWindow(CREATESTRUCT& cs)
{
	return CScrollView::PreCreateWindow(cs);
}

int CMainView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CScrollView::OnCreate(lpCreateStruct) == -1)
		return -1;

	return 0;
}

void CMainView::OnInitialUpdate()
{
	CRect client;
	GetClientRect(&client);
	SetScaleToFitSize(client.Size());

	m_view.CreateObject(CLSID_View);
	GetView()->Create((uintptr)GetDC()->GetSafeHdc(),Size(client.Size().cx,client.Size().cy));
	GetView()->CanvasRefreshing() += CanvasRefreshingEventHandler(this,&CMainView::OnCanvasRefreshing);
	GetView()->Scrolling() += ScrollEventHandler(this,&CMainView::OnScrolling);

	ShowScrollBar(SB_VERT);
	ShowScrollBar(SB_HORZ);

	CScrollView::OnInitialUpdate();
}

BOOL CMainView::PreTranslateMessage(MSG* pMsg)
{
	Win32EventArgs args(pMsg);
	if (GetView()->Event(&args))
		return TRUE;

	return __super::PreTranslateMessage(pMsg);
}

void CMainView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo/* = NULL*/)
{
	CScrollView::OnPrepareDC(pDC,pInfo);
}

void CMainView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CRect client;
	GetClientRect(&client);
	GetView()->Draw((uintptr)pDC->GetSafeHdc(),Size(client.Width(),client.Height()));
}

void CMainView::OnFilePrintPreview()
{
	AFXPrintPreview(this);
}

BOOL CMainView::OnPreparePrinting(CPrintInfo* pInfo)
{
	return DoPreparePrinting(pInfo);
}

void CMainView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

void CMainView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

void CMainView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
	GetView()->SetActive(bActivate ? true : false);
	return __super::OnActivateView(bActivate,pActivateView,pDeactiveView);
}

void CMainView::OnRButtonUp(UINT nFlags, CPoint point)
{
	nFlags;point;
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CMainView::OnContextMenu(CWnd* pWnd, CPoint point)
{
	pWnd;
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
}

IView* CMainView::GetView() const
{
	return sys::InterfacePtr<IView>(m_view);
}

void CMainView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	CView::OnHScroll(nSBCode,nPos,pScrollBar);
}

void CMainView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	int nMinPos = 0;
	int nMaxPos;
	GetScrollRange(SB_VERT, &nMinPos, &nMaxPos);
	int nMaxScrollRange;// = GetScrollLimit(SB_VERT);
	SCROLLINFO info;
	GetScrollInfo(SB_VERT, &info, SIF_ALL);
	nMaxScrollRange = nMaxPos - info.nPage;
	if(nMaxScrollRange < 0)
		nMaxScrollRange = 0;

	int nPreScrollPos = min(GetScrollPosition().y, nMaxScrollRange);
	int nCurScrollPos = nPreScrollPos;

	switch(nSBCode)
	{
	case SB_TOP:
		nCurScrollPos = nMinPos;
		break;
	case SB_ENDSCROLL:
		break;
	case SB_LINEUP:
		if(nCurScrollPos > nMinPos)
		{
			nCurScrollPos = nPreScrollPos - ((GetView()->GetScale() < 1) ? int(100/GetView()->GetScale()) : 1);
		}
		break;
	case SB_LINEDOWN:
		if(nCurScrollPos < nMaxScrollRange)
		{
			nCurScrollPos = nPreScrollPos + ((GetView()->GetScale()<1) ? int(100/GetView()->GetScale()) : 1);
		}
		break;
	case SB_PAGEUP:
		if(nCurScrollPos> nMinPos)
		{
			nCurScrollPos = nPreScrollPos - int(m_pageDev.cy);
		}
		break;
	case SB_PAGEDOWN:
		if(nCurScrollPos < nMaxScrollRange)
		{
			nCurScrollPos = nPreScrollPos + int(m_pageDev.cy);
		}
		break;
	case SB_BOTTOM:
		nCurScrollPos = nMaxScrollRange;
		break;
	case SB_THUMBPOSITION:
		nCurScrollPos = nPos;
		break;
	case SB_THUMBTRACK:
		nCurScrollPos = nPos;
		break;
	default:
		break;
	}

	if(nCurScrollPos < nMinPos)
		nCurScrollPos = nMinPos;
	if(nCurScrollPos > nMaxPos)
		nCurScrollPos = nCurScrollPos;

	CRect rcDelta(0, 0, nCurScrollPos, nCurScrollPos);
	GetDC()->DPtoLP(rcDelta);

	//view point
	CPoint viewpoint(GetView()->GetViewPoint().x,GetView()->GetViewPoint().y);
	viewpoint.y = -rcDelta.Height();
	GetView()->SetViewPoint(Point(viewpoint.x,viewpoint.y));

	CPoint point = viewpoint;
	point.y = rcDelta.Height();

	CRect rcScroll(CPoint(0,0),point);
	GetDC()->LPtoDP(&rcScroll);

	POINT ptDev;
	int xOrig = GetScrollPos(SB_HORZ);
	ptDev.x = xOrig;
	SetScrollPos(SB_HORZ, ptDev.x);
	int yOrig = GetScrollPos(SB_VERT);
	ptDev.y = (int)(rcScroll.Height()+0.5);
	SetScrollPos(SB_VERT, ptDev.y);
	CRect rect(0, 0, 0 ,0);
	GetClientRect(&rect);

	rect.top = rect.top + 50 +1;

	ScrollWindow(xOrig - ptDev.x, yOrig - ptDev.y, &rect, &rect);
}

void CMainView::OnCanvasRefreshing(const Rect& boundbox,bool whole)
{
	if (whole)
		Invalidate(FALSE);
	else
	{
		RECT rc;
		rc.left = (int)boundbox.X();
		rc.top = (int)boundbox.Y();
		rc.right = (int)boundbox.RightBottom().x;
		rc.bottom = (int)boundbox.RightBottom().y;
		InvalidateRect(&rc,TRUE);
		UpdateWindow();
	}
}

void CMainView::OnScrolling(const Size& size)
{
	if (Math::Greater(size.cx,0.0f))
	{
		SIZE mmsize = {Math::ToInt(size.cx),Math::ToInt(size.cy)};

		SetScrollSizes(MM_TEXT,mmsize);
	}
}